#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SERVER_PORT 6666
#define SERVER_IP "192.168.47.180"
// #define SERVER_IP "8.138.248.21"

#define CLIENT_PORT 8889
#define CLIENT_IP "192.168.47.165"

/*
in_addr_t inet_addr(const char *cp);  // 将主机IP 转成 网络IP
char *inet_ntoa(struct in_addr in);   // 将网络IP 转成  主机IP
uint16_t htons(uint16_t hostshort);  //  将主机端口号 转成 网络端口号
uint16_t ntohs(uint16_t netshort);   //  将网络端口号 转成 主机端口号

建立套接字 scocket   返回sockfd
int socket(int domain, int type, int protocol);
    domain 网络协议 AF_INET    AF_INET6
    type  SOCK_STREAM 选择TCP   SOCK_DGRAM 选择UDP

绑定自己的IP地址  和 端口号   0、-1
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    sockfd  套接字描述符
    addr    结构体sockaddr的指针 ip和端口
    addrlen  结构体的大小

listen()声明sockfd处于监听状态  0、-1
int listen(int sockfd, int backlog);
    sockfd ： 套接字文件描述符
    backlog  ：同时  最多支持连接上来的客户端总数


等待接受客户端连接  失败-1  返回已连接的套接字文件描述符
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    sockfd： 套接字文件描述符
    addr  ：  连接上来的客户端的IP地址和端口号
    addrlen ： 长度

接收数据  失败-1  返回0 表示客户端断开连接
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    sockfd： 已连接的套接字文件描述符  connectfd
    buf  ： 接收到的数据存储到这里
    len  ：  接收数据的大小
    flags  ：  一般设置为  0



发起连接 客户端发起连接  返回0  失败-1
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    sockfd  --> 套接字文件描述符
    addr   --- 【服务器的IP地址  和 端口号】
    addrlen  ---地址的长度    sizeof(struct sockaddr_in )


发送数据  返回发送的字节数  失败-1
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
*/

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 0 表示使用默认协议
    if (sockfd < 0)
    {
        perror("socket error");
        return -1;
    }

    // 创建Server端地址结构体
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;                   // 使用ipv4
    addr.sin_port = htons(SERVER_PORT);          // 端口   htons()  主机字节序转网络字节序host to net
    addr.sin_addr.s_addr = inet_addr(SERVER_IP); // ip  inet_addr() 将主机IP 转成 网络IP

    while (1)
    {
        // 连接到服务器
        if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
        {
            perror("connect error");
            close(sockfd);
            return -1;
        }

        printf("Connected to server successfully!\n");

        while (1)
        {
            // 从用户输入获取消息
            char buf[1024];
            printf("请输入消息:");
            fgets(buf, sizeof(buf), stdin);

            // 去除换行符
            buf[strcspn(buf, "\n")] = 0;

            // 检查是否退出
            if (strcmp(buf, "quit") == 0)
            {
                break;
            }

            // 发送消息到服务器
            if (send(sockfd, buf, strlen(buf), 0) < 0)
            {
                perror("send error");
                break;
            }

            printf("已发送: %s\n", buf);

            // 接收服务器返回的消息
            // recv(sockfd, buf, sizeof(buf), 0);
            // printf("收到: %s\n", buf);
        }
    }

    // 关闭套接字
    close(sockfd);

    return 0;
}

// https://newstar.wiki/learn/nc  tcp调试工具
// https://blog.csdn.net/qq_24305079/article/details/147476573 简易教程
// 模拟客户端  nc 192.168.46.2 11111
